03 Django 模板

模板的设计方式实现了 MVTM: Model, V: View, T: Template) 的解耦, VT 有着 N:M 的关系,一个 V 可以调用任意 T,一个 T 可以供任意 V 使用。

模板处理分为两个过程:
- 加载 HTML
- 渲染数据

模板主要有两个部分:
- HTML 静态代码
- 模板语言,动态插入的代码段(挖坑、填坑)

模板中的动态代码段除了做基本的静态填充,还可以实现一些基本的运算,转换和逻辑。

静态页面:页面数据是本地固定的
动态页面:页面数据来源于后台服务器

模板中的变量: 视图转递给模板的数据,遵赛标识符规则
- 语法:{{ var }}
- 如果变量不存在,则插入空字符串

注意在模板语言中,方法(函数)不能有参数,列表索引也不允许使用负索引。
- 方法(函数)不能有参数。如 strupper 函数,不能用{{ str.upper() }} 调用,只能用 {{ str.upper }} 调用。
- 列表索引不允许使用负索引。如 items = ["apples", "bananas", "carrots"],获取 carrots 可以用 {{ items.2 }},不能用 {{ items.-1 }}

模板中的标签:
- 语法 {% tag %}
- 作用:
- 加载外部传入的变量
- 在输出中创建文本
- 控制循环(for)或逻辑(if

if 语句:

单分支

{% if 表达式 %}
	语句
{% endif %}

双分支

{% if 表达式 %}
	语句
{% else %}
	语句
{% endif%}

多分支

{% if 表达式 %}
	语句
{% elif 表达式%}
	语句
{% else %}
	语句
{% endif %}

判断 turefalse

{% if today_is_weekend %}
	<p> Welcom to the weekend!</p>
{% endif %}

使用 and, or, not

{% if athlete_list and coach_list %}
	<p>Both athletes and coaches are available</p>
{% endif %}

{% if not athlete_list %}
	<p>There are no athletes.</p>
{% endif %}

{% if athlete_list or coach_list %}
	<p>There are some athletes or some coaches</p>
{% endif %}

使用 in, not in

{% if "bc" in "abcdef" %}
	<p> This paragraph will be appear since "bc" is a substring of "abcdef" </p>
{% endif %}

{% if user not in users %}
	<p> Assumed users is a list, this paragraph will be appear if user isn't an element of the list.</p>
{% endif %}

for 语句

{% for 变量 in 列表 %}
	语句1
{% empty %}
	语句2
{% endfor %}

# 变量在列表中时执行语句1,列表为空时执行语句2

?: 列表循环完后,会不会执行语句2。不管列表为何值,empty 后的语句总是执行?

当列表为空值是,才会执行 empty 后的语句。列表可以循环,则列表不为空,不执行 empty 后的语句。列表循环完后,列表的值不变,仍不为空值,empty 后的语句也不执行。

?: 如果,语句1 中有删除列表元素的操作呢?

一个特殊变量:****{{ forloop.counter }} 表示当前是第几次循环,从 1 开始。

{% for item in todo_list %}
	<p> {{forloop.counter }}: {{ item }} </p>
{% endfor %}

{{ forloop.counter0 }}:当前是第几次循环,从 0 开始
{{ forloop.revcounter }}:当前是第几次循环,倒着数数,到 1 停
{{ forloop.revcounter0 }}:当前是第几次循环,倒着数数,到 0 停
{{ forloop.first }}:是否是第一个,布尔值
{{ forloop.last }}:是滞是最后一个,布尔值

{{ forloop.parentloop.counter }}:当前循环的父循环(上层循环)是第几次循环。也有 counter0, revcounter, revcounter0, first, last

# forloop.first
{% for object in objects %}
	{% if forloop.first %}
		<li class="first">
	{% else %}
		<li>
	{% endif %}
	{{ object }}</li>
{% endfor %}

# forloop.last
{% for link in links %}
	{{ link }}{% if not forloop.last %}| {% endif %}
{% endfor%}

# forloop.parentloop
{% for country in countries %}
	<table>
		{% for city in country.city_list %}
			<tr>
				<td>Country #{{ forloop.parentloop.counter }}</td>
				<td>City #{{ forloop.counter }}</td>
				<td>{{ city }}</td>
			</tr>
		{% endfor %}
	</table>
{% endfor %}

注释:

单行注释:{# 注释内容 #}

多行注释:

{% comment %} 
	内容 
{% endcomment %}

过滤器:{{ var|过滤器 }}在变量显示前修改

加法过滤器,add{{ value|add:2 }}value2

没有减法过滤器,但可以加负值{{ value|add:-2 }}value2

全小写过滤器,lower{{ name|lower }}name 所有字符转为小写。

全大写过滤器,upper{{ name|upper }}name 所有字符转为大写。

可迭代变量的第一个值,first{{ my_list|first }}my_list 的第一个值。

可以加多个过滤器{{ my_list|firs|upper }}my_list 的第一个值全部大写(从左往右)。

截断,truncatechars{{ bio | truncatechars: 30}},截取 bio 的前 30 个字符。

过滤器可以传递参数,参数需要使用引号引起来,join{{ students | join: "="}}

默认值,default{{ var|default:value }}var 为空值时,显示 value 的值

日期格式化输出,date{{ dateVal | date: "y-m-d" }},按 y-m-d 格式将 dateVal 转换后输出(显示)

HTML 转义,safe
渲染成 html{{ code|safe }}
关闭自动转义:{% autoescape off %} code {% endautoescape %}
打开自动转义:{% autoescape on %} code {% endautoescape %

模板继承

模板继承中包含 blockextendsincludeblock.super 等内容。

block

在父模板中使用 block 挖坑:block 后跟块(坑)名

{% block posName %}  # posName 是这个块(坑)的名称
	code
{% endblock %}

extends

在子模板中使用 extends继承父模板,写在开头位置。

{% extends '父模板路径' %}

然后再使用 block 将父模板中使用 block 挖得同名坑填上:

{% block posName %}
	code
{% endblock %}

include

加载模板进行渲染,即将其他 htlm 文件内容加载进来,并放在 include 的位置。

{% include 'smeCode.html' %}

smeCode.html 的内容加到当前页面的 {% include "smeCode.html" %} 的位置,即用 smeCode.html 的内容替换 {% include "smeCode.html" %} 语句。应该解释清楚了吧。

block.super

block.super 是变量,使用时用 {{ }},获取父模板中 block 的内容:

{{ block.super }}

默认情况下,子模板的内容会覆盖父模板的内容,如果想将父模板的内容显示出来,需要用 block.super 将父模板的内容继承过来。